package psn.kiko.aop.debounce;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import psn.kiko.pojo.R;

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;

@Aspect
@Component
public class DebounceAspect{
	private final ConcurrentHashMap<String,Long> debounceMap = new ConcurrentHashMap<>();
	
	@Around("@annotation(psn.kiko.aop.debounce.Debounce)")
	public Object debounce(ProceedingJoinPoint joinPoint) throws Throwable{
		DebounceConfig config = debounceConfig(joinPoint);
		long currentTimeMillis = System.currentTimeMillis();
		Long lastTimeMillis = debounceMap.get(config.getKey());
		if(lastTimeMillis != null&&( currentTimeMillis-lastTimeMillis ) < config.getValue()){
			SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
			Date last = new Date(lastTimeMillis);
			Date now = new Date(currentTimeMillis);
			DebounceRequest requestInfo = DebounceRequest.builder().lastRequestTime(format.format(last))
					.currentRequestTime(format.format(now))
					.standardInterval(config.getValue())
					.actualInterval(currentTimeMillis-lastTimeMillis).build();
			return R.failWithMsgAndData("短时间内试图重复进行业务操作",requestInfo);
		}
		debounceMap.put(config.getKey(),currentTimeMillis);
		return joinPoint.proceed(joinPoint.getArgs());
	}
	
	private DebounceConfig debounceConfig(ProceedingJoinPoint joinPoint){
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		Method method = signature.getMethod();
		String className = method.getDeclaringClass().getName();
		String methodName = method.getName();
		Debounce debounce = method.getAnnotation(Debounce.class);
		long debounceTime = debounce.value();
		return DebounceConfig.builder().key(className+"."+methodName).value(debounceTime).build();
	}
}
